﻿


using IoTClient;
using IotClientService.Operations.hk;
using IotContract.Dtos.Clients.Equips;
using IotContract.Dtos.Servers;
using IotContract.Enums;
using IotContract.Events;
using IotContract.Interfaces;
using IotContract.Models.Clients;
using Newtonsoft.Json;
using SyncSocketModuleCore.SyncSocketModule;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using XT.Common.Extensions;

namespace IotClientService.Operations.bcr;
public class HbcBcrOperation : IEquipOperation<BcrEquipDto>
{
    private BcrEquipDto _equipInfo;
    private SocketClient _socketClient;
    private CommStep _currentCommStep;
    private Task _operationTask;
    private int _currentTryConnectPort;
    private string _ipAddress = string.Empty;
    private bool _status = false;
    private bool _curConnection;
    private bool _isReceived = false;
    private int _bcrReadCnt = 0;
    private DateTime _connectRetryTime;
    private DateTime _sendRetryTime = DateTime.Now;
    private int _connectionCheckCount;
    private int _recvBytesCount;
    private List<string> _packetList = new List<string>();
    private string _receiveData = "";
    private string _receiveDataTemp = "";
    private string _packetTemp = "";
    
    private CancellationTokenSource _cancellationTokenSource;
    public event EventHandler<ConnectStatusEventArgs> OnConnectStatusChanged;

  

    public bool GetConnection()
    {
        return _curConnection;
    }

    public BcrEquipDto GetEquipInfo()
    {
        return _equipInfo;
    }

    public bool GetOperationStatus()
    {
        return _status;
    }

    /// <summary>
    /// 初始化数据
    /// </summary>
    /// <param name="group"></param>
    /// <param name="tags"></param>
    /// <returns></returns>
    public async Task<bool> Init(BcrEquipDto group, IEnumerable<EquipTagDto> tags = null)
    {
        _equipInfo = group;

        await OperationStop();
        _currentCommStep = CommStep.Init;

        // 解析ipaddress
        var ips = _equipInfo.IPAddress.Split(":");
        if (ips.Length != 2)
        {
            return false;
        }
        _ipAddress = ips[0];
        _currentTryConnectPort = ips[1].To<int>();



        _currentCommStep = CommStep.WaitConnect;
        _packetList.Clear();
        _cancellationTokenSource = new CancellationTokenSource();

        return true;
    }

    private void m_SocketClient_OnConnect(bool connected)
    {
        if (!connected)
        {
            _equipInfo.ReadingStep = BcrProcessStepType.Disconnected;
            if (_curConnection)
            {
                BcrStepLogging(BcrProcessStepType.Disconnected);
            }
            _curConnection = false;
        }
    }
    /// <summary>
    /// 数据接收
    /// </summary>
    /// <param name="receiveData"></param>
    /// <exception cref="NotImplementedException"></exception>
    private void m_SocketClient_OnReceive(string recvData)
    {
        if (!string.IsNullOrEmpty(recvData))
        {
            BcrStepLogging(BcrProcessStepType.Receive_ReadPacket, recvData.Substring(0, 10));
        }

        if (_isReceived) return;
        _recvBytesCount = recvData.Length;
        if (recvData.IndexOf("%") >= 0)
        {
            _currentCommStep = CommStep.WaitDisConnect;
            _equipInfo.ReadingStep = BcrProcessStepType.IDLE;
            _sendRetryTime = DateTime.Now;
            _connectionCheckCount = 0;
            return;
        }
        _receiveData += recvData;
        _receiveData = _receiveData.Replace("\0", "");
       
    
          int  packetEnd = _receiveData.IndexOf($"{'\r'}");
        
       

        _receiveDataTemp = _receiveData.ToString();
        if (packetEnd >= 0)
        {
            
             _packetTemp = _receiveDataTemp.Substring(0, packetEnd+1);
            
            if (_packetTemp.Length > 2)
            {
               
                    _packetList.Add(_packetTemp);
                
            }
           
        }


        if (_packetList.Count > 0)
        {

            _isReceived = true;
            ProcessReceivePacket();
            _isReceived = false;
        }
        else
        {
            _equipInfo.ReadingStep = BcrProcessStepType.Read_OK;
            _equipInfo.Value = "";
        }
    }
    /// <summary>
    /// 接收解析数据
    /// </summary>
    /// <returns></returns>
    private bool ProcessReceivePacket()
    {
        if (_socketClient == null)
        {
            return false;
        }

        bool readOKLayer = false;
       

        string packet = "";
        int packetStart = 0;
        int packetEnd = 0;
        string Logging = "";
        for (int i = 0; i < _packetList.Count; i++)
        {
            packet = _packetList[i];
            // packetStart = packet.IndexOf($"{'\u0002'}");
            packetStart = 0;
            packetEnd = packet.IndexOf($"{'\r'}");
          
          
            if (!readOKLayer)
            {
                if (packet.ToLower().IndexOf("error") >= 0)
                {
                    //// 扫到ERROR，进行报警
                    //DataManager.DataGrpcService.CallFireWarn(new EVE.ECS_Model.Server.Process.EcsEquipWarn
                    //{
                    //    GroupNumber =int.Parse(_group.PlcName),
                    //    EquipType = EVE.ECS_Model.Client.UnitType.BCR,
                    //    ErrorTime = DateTime.Now,
                    //    ErrorCode="ERROR"
                    //});
                    _equipInfo.ReadingStep = BcrProcessStepType.Read_Fail;
                    _equipInfo.RecieveTime = DateTime.Now;
                    _equipInfo.Value = packet.Substring(packetStart, packetEnd);
                    BcrStepLogging(BcrProcessStepType.Read_Fail);
                }
                else
                {
                    if (packetEnd >= 0)
                    {
                        var packdata = packet.Substring(packetStart, packetEnd);

                        _equipInfo.Value = packdata;
                    }
                    _equipInfo.ReadingStep = BcrProcessStepType.Read_OK;
                    _equipInfo.RecieveTime = DateTime.Now;
                    BcrStepLogging(BcrProcessStepType.Read_OK);
                }

                readOKLayer = true;
            }
          
        }
        _packetList.Clear();
        return true;
    }
    /// <summary>
    /// 启动
    /// </summary>
    /// <returns></returns>
    public async Task<bool> OperationStart()
    {
        // 连接Socket
        Task.Run(() =>
         {
             var result = ConnectServer();
             if (!result)
             {
                 var error = $"{_equipInfo.ToString()} 启动失败，无法连接";

                 _equipInfo.Remark= error ;
                 OnConnectStatusChanged.Invoke(this, new ConnectStatusEventArgs
                 {
                     Connect = _curConnection,
                     IsSuccess = false,
                     Message = error
                 });
                 return false;
             }
             return true;
         }).ContinueWith(t =>
         {
             if (t.Result)
             {
                 _operationTask = Task.Factory.StartNew(() => ThreadScheduler(), _cancellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
                 _status = true;
                 return true;
             }
             else
             {
                 return false;
             }
         });

        return true;

       
        
    }
    private async Task ThreadScheduler()
    {

        while (true)
        {
            if (_cancellationTokenSource.IsCancellationRequested)
            {
                break;
            }
            try
            {
                DoingSchedule();
                await Task.Delay(_equipInfo.Pooling);
            }
            catch (Exception exception)
            {
                OnConnectStatusChanged?.Invoke(this, new ConnectStatusEventArgs
                {
                    Message = exception.Message,
                    Connect = false,
                    IsSuccess = false

                });
            }


        }
    }

    private void DoingSchedule()
    {

        _ = $"CurrentStep : {_currentCommStep} , Error Event ";




        switch (_currentCommStep)
        {
            case CommStep.WaitConnect:
                if (CheckUpperTimer(_connectRetryTime, 10000))
                {
                    // 连接Socket
                    ConnectServer();
                }
                break;
            case CommStep.Run:
                if (!_socketClient.IsConnected())
                {
                    _connectionCheckCount++;
                    if (_connectionCheckCount > 3)
                    {
                        _currentCommStep = CommStep.WaitDisConnect;
                        _equipInfo.ReadingStep = BcrProcessStepType.IDLE;
                        _sendRetryTime = DateTime.Now;
                        _connectionCheckCount = 0;
                    }
                    break;
                }
                _connectionCheckCount = 0;

                if (!_curConnection || !CheckUpperTimer(_connectRetryTime, 5000))
                {
                    break;
                }
                // 间隔时间大于
                if (_equipInfo.ReadingStep == BcrProcessStepType.Read_Request && CheckUpperTimer(_sendRetryTime, 7200000))
                {
                    _currentCommStep = CommStep.WaitDisConnect;

                    _equipInfo.ReadingStep = BcrProcessStepType.IDLE;
                    _sendRetryTime = DateTime.Now;
                    break;
                }
                if (_equipInfo.ReadingStep == BcrProcessStepType.Read_Request && CheckUpperTimer(_sendRetryTime, 10000) && CheckUpperTimer(_connectRetryTime, 5000))
                {

                    if(_isReceived) { break; }

                    ReadWord();

                    _sendRetryTime = DateTime.Now;
                }
                else if (_equipInfo.ReadingStep == BcrProcessStepType.Send_ReadPacket && _packetList.Count > 0)
                {

                   
                    if (CheckUpperTimer(_sendRetryTime, 8000))
                    {
                        _equipInfo.ReadingStep = BcrProcessStepType.Read_Request_TimeOrver;

                    }
                }
                else if (_equipInfo.ReadingStep == BcrProcessStepType.Read_OK || _equipInfo.ReadingStep == BcrProcessStepType.Read_Complete)
                {
                    _bcrReadCnt = 0;
                }
                if (_equipInfo.ReadingStep == BcrProcessStepType.NoRead || _equipInfo.ReadingStep == BcrProcessStepType.Read_Fail || _equipInfo.ReadingStep == BcrProcessStepType.Read_Request_TimeOrver)
                {
                    _bcrReadCnt++;
                    if (_bcrReadCnt > 2)
                    {
                        _equipInfo.ReadingStep = BcrProcessStepType.Read_RetryStop;
                    }
                    else
                    {
                        _equipInfo.ReadingStep = BcrProcessStepType.Read_Request;
                    }

                }
                break;
            case CommStep.WaitDisConnect:
                if (_socketClient.IsConnected())
                {
                    _socketClient.Close();
                }
                _currentCommStep = CommStep.WaitConnect;

                _connectRetryTime = DateTime.Now;
                break;
            case CommStep.WaitInit:
            case CommStep.Init:
                break;
        }
    }

    private bool ReadWord()
    {

        _receiveData = "";
        _packetList.Clear();  
       _equipInfo.Value = "";
        string packet = $"LON{'\r'}";
          
       SendPacket(packet);
        
        return true;
    }
    /// <summary>
    /// 发送读取信息报文
    /// </summary>
    /// <param name="strData"></param>
    private void SendPacket(string strData)
    {
        Encoding.UTF8.GetBytes(strData);
        byte[] SendBuffer = Encoding.ASCII.GetBytes(strData);
        _socketClient.Send(SendBuffer, 0, SendBuffer.Length, SocketFlags.None);
        _equipInfo.ReadTime = DateTime.Now;
        _equipInfo.RecieveTime = null;
        _equipInfo.ReadingStep = BcrProcessStepType.Send_ReadPacket;
        BcrStepLogging(_equipInfo.ReadingStep, strData);
    }
    /// <summary>
    /// 检查是否超时
    /// </summary>
    /// <param name="Time"></param>
    /// <param name="ReadInterval"></param>
    /// <returns></returns>
    private bool CheckUpperTimer(DateTime Time, int ReadInterval)
    {
        if ((DateTime.Now - Time).TotalMilliseconds > (double)ReadInterval)
        {
            return true;
        }
        return false;
    }
    /// <summary>
    /// 连接服务
    /// </summary>
    /// <returns></returns>
    private bool ConnectServer()
    {
       

        if (_socketClient == null)
        {
            _socketClient = new SocketClient(_ipAddress, _currentTryConnectPort);
            _socketClient.TcpSyncSocketReceive += m_SocketClient_OnReceive;
            _socketClient.TcpSyncSocketConnected += m_SocketClient_OnConnect;
            
        }
        if (_socketClient.IsConnected())
        {

            _socketClient.Close();

            _socketClient = new SocketClient(_ipAddress, _currentTryConnectPort);
            _socketClient.TcpSyncSocketReceive -= m_SocketClient_OnReceive;
            _socketClient.TcpSyncSocketConnected -= m_SocketClient_OnConnect;
            _socketClient.TcpSyncSocketReceive += m_SocketClient_OnReceive;
            _socketClient.TcpSyncSocketConnected += m_SocketClient_OnConnect;


            _socketClient.Clear();
        }

        var result = _socketClient.Connect(_ipAddress, _currentTryConnectPort);
        if (!result)
        {
            _equipInfo.ReadingStep = IotContract.Enums.BcrProcessStepType.Disconnected;
            BcrStepLogging(BcrProcessStepType.Disconnected);
            _curConnection = false;

            return false;
        }
        else
        {
            _curConnection = true;
            _currentCommStep = CommStep.Run;
            BcrStepLogging(BcrProcessStepType.Connected);
            _equipInfo.ReadingStep = BcrProcessStepType.IDLE;

        }
        _connectRetryTime = DateTime.Now;

        return true;

    }

    
    /// <summary>
    /// bcr日志
    /// </summary>
    /// <param name="BCRStep"></param>
    /// <param name="AddMsg"></param>
    public void BcrStepLogging(BcrProcessStepType BCRStep, string AddMsg = "")
    {

       
        string logMsg = $"{_equipInfo.ToString()} LayerNum {_equipInfo.OrderNum}";
        if (AddMsg != "")
        {
            AddMsg = AddMsg.Replace("\r", "");
            logMsg = logMsg + "," + AddMsg;
        }
        this.OnConnectStatusChanged?.Invoke(this, new ConnectStatusEventArgs
        {
            Connect =_curConnection,
            IsSuccess = true,
            Message = logMsg
        });

    }
    /// <summary>
    /// 停止数据
    /// </summary>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<bool> OperationStop()
    {
        _cancellationTokenSource?.Cancel();

        _socketClient?.Close();

        _status = false;

        OnConnectStatusChanged.Invoke(this, new ConnectStatusEventArgs
        {
            Connect = false,
            IsSuccess = true,
        });

        return true;
    }
    /// <summary>
    /// 写入请求
    /// </summary>
    /// <param name="writeInfo"></param>
    /// <returns></returns>
    public async Task<bool> WriteRequest(OperationWriteCommand writeInfo)
    {
        if (writeInfo.Id.IsNullOrEmpty())
        {
            _equipInfo.WriteId = String.Empty;
            _equipInfo.Value = String.Empty;

            return true;
        }
       
        _equipInfo.Value = String.Empty;
        _bcrReadCnt = 0;


        _equipInfo.WriteId = writeInfo.Id;

        _equipInfo.ReadingStep = BcrProcessStepType.Read_Request;

        return true;
    }

    public void Dispose()
    {
        OperationStop();
    }
}
